# Makefile for RISC-V bare-metal

# Toolchain
CC      = riscv64-unknown-elf-gcc
AS      = riscv64-unknown-elf-as
LD      = riscv64-unknown-elf-ld
OBJCOPY = riscv64-unknown-elf-objcopy
OBJDUMP = riscv64-unknown-elf-objdump

# Compilation flags
CFLAGS  = -march=rv64i -mabi=lp64 -mcmodel=medany -O3
ASFLAGS = -march=rv64i -mabi=lp64
LDSCRIPT = link.lds

# Source and intermediate files
SRCDIR    = src
BUILDDIR  = build

# Collect all C source files in src/
SRC_C     := $(wildcard $(SRCDIR)/*.c)
SRC_S     = $(SRCDIR)/start.asm

OBJ_C     := $(patsubst $(SRCDIR)/%.c, $(BUILDDIR)/%.o, $(SRC_C))
ASM_C     := $(patsubst $(SRCDIR)/%.c, $(BUILDDIR)/%.asm, $(SRC_C))
OBJ_S     = $(BUILDDIR)/start.o

ELF     = $(BUILDDIR)/main.elf
BIN     = $(BUILDDIR)/main.bin
DUMP    = $(BUILDDIR)/main.txt

.PHONY: all clean info help

# Default target
all: info $(BUILDDIR) $(ASM_C) $(BIN) $(DUMP) up_to_date

# Show current build configuration
info:
	@echo "Building for RV64 architecture"
	@echo "Cross compiler: riscv64-unknown-elf-gcc"
	@echo "March: rv64i, Mabi: lp64"

# Create build directory if it doesn't exist
$(BUILDDIR):
	mkdir -p $@

# 1. C source -> Assembly
$(BUILDDIR)/%.asm: $(SRCDIR)/%.c | $(BUILDDIR)
	$(CC) $(CFLAGS) -S $< -o $@

# 2. Assembly -> Object file
$(BUILDDIR)/%.o: $(BUILDDIR)/%.asm
	$(AS) $(ASFLAGS) $< -o $@

# 3. Handwritten assembly -> Object file
$(OBJ_S): $(SRC_S) | $(BUILDDIR)
	$(AS) $(ASFLAGS) $< -o $@

# 4. Link objects to ELF
$(ELF): $(OBJ_S) $(OBJ_C) $(LDSCRIPT)
	$(LD) -T $(LDSCRIPT) $(OBJ_S) $(OBJ_C) -o $@

# 5. ELF -> Binary image
$(BIN): $(ELF)
	$(OBJCOPY) -S -O binary $< $@

# 6. Disassemble ELF to readable text
$(DUMP): $(ELF)
	$(OBJDUMP) -D $< > $@

clean:
	rm -rf $(BUILDDIR)

up_to_date:
	@echo "Build complete."

help:
	@echo "Usage:"
	@echo "  make           # Build for RV64 bare-metal"
	@echo "  make clean     # Clean build files"
	@echo "  make help      # Show this help"